/*
 * Copyright (c) 2011 Arron Bailiss <arron@arronbailiss.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


(function($) {
	
	var settings = {
		'toArea'     : null, // The selector where the dynamically loaded content should be inserted in the current page and extracted from on the dynamically loaded page
		'updateTitle': true, // Set to false to stop the page title being updated with the dynamically loaded content's page title
		'callback'   : null // Called after the page content has been loaded
	};
	var History = null;
	var selector = '';
	var justPushedState = false;
	var loading = false;
	
	var methods = {
		init : function(options) { // Initialises the plugin
			selector = this.selector;
			if (options) $.extend(settings, options);
			
			if (settings.toArea === null) {
				$.error('Missing required parameter toArea on jQuery.dynamicPage');
				return false;
			}
			
			if (methods.supported()) methods.bindEvents.call($(this));
			return $(this);
		},
		supported : function() { // Checks support for functionality
			History = window.History;
			return History.enabled;
		},
		bindEvents : function() { // Bind plugin events
			$(selector).live('click', function(e) { // Bind event for dynamic content loading links
				e.preventDefault();
				methods.loadContent.call($(this), $(this).attr('href'), true);
			});
			History.Adapter.bind(window, 'statechange', function(e) { // Bind state change for preserving back/forwards browser button functionality when loading dynamic content
				var state = History.getState();
				if (state !== null && !justPushedState) methods.loadContent(state.url);
			});
		},
		loadContent : function(url, doState) { // Fired when a dynamic content loading link is clicked
			if (!loading) {
			    loading = true;
			    $(settings.toArea).load(url+' '+settings.toArea+' > *', function(resp) { // Load the clicked link's href page's content in to toArea
				    if (settings.updateTitle) document.title = $(resp).filter('title').text(); // Update the page title
				    if (doState !== undefined) { // Magic HTML5 loveliness
					    stateObj = { url: url };
					    justPushedState = true;
					    History.pushState(stateObj, '', url);
					    justPushedState = false;
				    }

				    if (typeof settings.callback == 'function') settings.callback.call($(this), url); // Fire the callback
				    loading = false;
			    });
			}
		}
	};
	
	$.fn.dynamicPage = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		}
		else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		}
		else {
			$.error('Method '+method+' does not exist on jQuery.dynamicPage');
		}
	};
})(jQuery);